package com.lanyou.cook.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.entity.domain.DBlinkInterface;
import com.lanyou.cook.entity.domain.DBlinkInterfaceColumnDefinition;
import com.lanyou.cook.entity.domain.FieldSystem;
import com.lanyou.cook.repository.DBlinkInterfaceColumnDefinitionRepository;
import com.lanyou.cook.repository.DBlinkInterfaceRepository;
import com.lanyou.cook.repository.DBlinkRepository;
import com.lanyou.cook.repository.FieldSystemRepository;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.cook.util.gson.GsonUtil;
import com.lanyou.cook.web.param.DBlinkInterfaceParam;

/**
 * 
 * @author 曾族根
 *
 */ 
@RestController
@RequestMapping(Constants.BASE_URL_API + "/dBlinkInterfaces")
public class DBlinkInterfaceController {
	@Autowired
	private UserSessionService userSessionService;
	@Autowired
	private DBlinkInterfaceRepository dblinkInterfaceRepository;
	@Autowired
	private FieldSystemRepository fieldSystemRepository;
	@Autowired
	private DBlinkRepository dBlinkRepository;
	@Autowired
	private DBlinkInterfaceColumnDefinitionRepository dBlinkInterfaceColumnDefinitionRepository;

	/**
	 * 查询带参数条件的所有dblink接口
	 * 
	 * @param param
	 *            类型:String
	 * @param pageable
	 *            类型:String
	 * @return 带分页的所有参数条件下的dblink接口
	 */
	@RequestMapping("/search/findByExample")
	@RequiresPermissions(value={"dbLinkRelationInterfaceManagement:view","dbLinkRelationInterfaceManagement:maintain"},logical=Logical.OR)
	public Page<DBlinkInterface> findByExample(DBlinkInterfaceParam param, Pageable pageable) {

		Specification<DBlinkInterface> spec = new Specification<DBlinkInterface>() {
			@Override
			public Predicate toPredicate(Root<DBlinkInterface> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();
				if (StringUtils.isNotBlank(param.getName())) {
					predicatesList.add(cb.like(root.get("name"), '%' + param.getName() + '%'));
				}

				if (StringUtils.isNotBlank(param.getDblinkName())) {
					predicatesList.add(cb.equal(root.get("dblink").get("id"), param.getDblinkName()));
				}

				if (StringUtils.isNotBlank(param.getFieldName())) {
					predicatesList.add(cb.equal(root.get("fieldSystem").get("field").get("id"), param.getFieldName()));
				}

				if (StringUtils.isNotBlank(param.getFieldSystemName())) {
					predicatesList.add(cb.equal(root.get("fieldSystem").get("id"), param.getFieldSystemName()));
				}else{
					Path<String> pathOwnerFieldSystemId = root.get("fieldSystem").get("id");
					// 默认查当前登录用户所管理的领域系统
					Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
					if(!CollectionUtils.isEmpty(fieldSystemIds)){
						predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
					}else {
						predicatesList.add(cb.notEqual(cb.literal(1), 1));
					}
				}

				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};
		return dblinkInterfaceRepository.findAll(spec, pageable);
	}

	/**
	 * dblink接口的保存和新增
	 * 
	 * @param paramStr
	 *            类型:String
	 * @return 类型:String JSON格式的结果
	 */
	@RequestMapping(value = "/saveOrUpdate", method = RequestMethod.POST, produces = "application/json")
	@Transactional
	@RequiresPermissions(value={"dbLinkRelationInterfaceManagement:maintain"})
	public String saveOrUpdate(@RequestBody String paramStr) {
		JsonObject jsonParam = GsonUtil.getDefaultJsonParser().parse(paramStr).getAsJsonObject();
		String id = GsonUtil.getString(jsonParam, "id", "");
		String name = GsonUtil.getString(jsonParam, "name", "");
		String remark = GsonUtil.getString(jsonParam, "remark", "");
		String fieldSystemId = GsonUtil.getString(jsonParam, "fieldSystemId", "");
		String dblinkId = GsonUtil.getString(jsonParam, "dblinkId", "");
		JsonArray columnDefinitionJsonArray = jsonParam.getAsJsonArray("columnDefinitions");
		
		DBlinkInterface dblinkInterfacecheck = dblinkInterfaceRepository.findByname(name);
		if(dblinkInterfacecheck!=null){
			System.out.println(id);
			System.out.println(dblinkInterfacecheck.getId());
			if(!StringUtils.equals(dblinkInterfacecheck.getId(), id)){
				JsonObject result = new JsonObject();
				result.addProperty("isCanSave", false);
				result.addProperty("reason", "数据库中已存在，不能保存！");
				return result.toString();
			}
		}
		
		
		DBlinkInterface dBlinkInterface = dblinkInterfaceRepository.findOne(DBlinkInterface.idSpecification(id));
		if (dBlinkInterface == null) {
			dBlinkInterface = new DBlinkInterface();
		}
		dBlinkInterface.setName(name);
		dBlinkInterface.setRemark(remark);
		dBlinkInterface.setFieldSystem(fieldSystemRepository.findOne(FieldSystem.idSpecification(fieldSystemId)));
		dBlinkInterface.setDblink(dBlinkRepository.findOne(dblinkId));
		dblinkInterfaceRepository.save(Arrays.asList(dBlinkInterface));

		if (StringUtils.isNotEmpty(id)) {
			// 删除原有的列定义
			List<DBlinkInterfaceColumnDefinition> originalColumnDefinitions = dBlinkInterfaceColumnDefinitionRepository
					.findByDblinkInterface_Id(id);
			dBlinkInterfaceColumnDefinitionRepository.deleteInBatch(originalColumnDefinitions);

		}

		Collection<DBlinkInterfaceColumnDefinition> newColumnDefinitions = new Gson()
				.fromJson(columnDefinitionJsonArray, new TypeToken<Collection<DBlinkInterfaceColumnDefinition>>() {
				}.getType());

		if (CollectionUtils.isNotEmpty(newColumnDefinitions)) {
			for (DBlinkInterfaceColumnDefinition cd : newColumnDefinitions) {
				cd.setDblinkInterface(dBlinkInterface);
			}
			dBlinkInterfaceColumnDefinitionRepository.save(newColumnDefinitions);
		}

		JsonObject result = new JsonObject();
		result.addProperty("success", true);
		return result.toString();

	}
}
